<template>
  <div
    :class="'heat-map-wrap ' + wrapId"
    :key="wrapId"
    :id="wrapId"
    :ref="wrapId"
    :style="{ height: height, width: width }"
  >
    <div :id="id" :ref="id" :class="'chart ' + className"></div>
  </div>
</template>
<script>
import echarts from 'echarts'
import { isFunction, each, max, min, chunk, sortBy, merge } from 'lodash'
import chartResize from '@/mixins/chartResize'
import config from '@/config'
import store from '@/store'
require('echarts/extension/bmap/bmap')

const COLORS = ['#0000ff', '#ffff00', '#ff0000']

export default {
  mixins: [chartResize],
  props: {
    className: {
      type: String,
      default: ''
    },
    id: {
      type: String,
      default: 'heat-map'
    },
    defaultOptions: {
      type: Object,
      default: null
    },
    width: {
      type: String,
      default: '100%'
    },
    height: {
      type: String,
      default: '100%'
    },
    fetchData: {
      type: Function
    },
    chartData: {
      type: Array,
      default: null
    },
    params: {
      type: Object
    },
    shrink: {
      type: Boolean
    },
    operArea: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      gapSize: 0,
      lngExtent: [],
      latExtent: [],
      cellCount: [],
      overlays: [],
      visualMapMax: 0,
      visualMapMin: 0
    }
  },
  computed: {
    wrapId() {
      return this.id + '-chart'
    }
  },
  watch: {
    chartData() {
      this.chartRest()
    },
    shrink() {
      this.chartRest()
      window[this.id].resize()
    }
  },
  mounted() {
    window[this.id] = echarts.init(document.getElementById(this.id), config.echartsthemeName)
    window[this.id].on('click', this.areaClickHandle)
    this.modifyParams()
    this.initChart()
    if (isFunction(this.fetchData)) {
      this.getMapData()
    }
  },
  beforeDestroy() {
    if (!window[this.id]) {
      return
    }
    window[`${this.id}-drawingManager`].removeEventListener('overlaycomplete', this.overlaycomplete)
    window[this.id].off('click')
    window[this.id].dispose()
    window[this.id] = null
    window[`${this.id}-drawingManager`] = null
  },
  methods: {
    chartRest() {
      if (this.chartData.length > 0) {
        window[this.id].clear()
      }
      window[this.id].hideLoading()
      this.modifyParams()
      const countMax = this.selectCountMax(this.chartData)
      this.visualMapMax = countMax
      this.$nextTick(() => {
        this.initChart()
      })
    },
    /**
     * @name: selectCountMax
     * @test: test font
     * @msg: 筛选数据中显示最大值
     * @param {type}
     * @return:
     */
    selectCountMax(data) {
      const l = []
      each(data, item => {
        l.push(item[2])
      })
      return max(l)
    },
    modifyParams() {
      const { xMinSize, xMaxSize, yMinSize, yMaxSize, xCut, yCut } = this.params
      this.lngExtent = [xMinSize, xMaxSize]
      this.latExtent = [yMinSize, yMaxSize]
      this.cellCount = [xCut, yCut]
    },
    pieces() {
      const countArr = []
      const colorArr = []
      each(this.chartData, item => {
        countArr.push(item[2])
      })
      // 数据按照count（数组第三个参数进行）等比例划分
      const newArr = chunk(
        sortBy(countArr, count => Number(count)),
        countArr.length * 0.2
      )
      colorArr.push({
        value: 0,
        color: '#ffffff'
      })
      each(newArr, (item, index) => {
        const len = item.length - 1
        colorArr.push({
          min: item[0],
          max: item[len],
          color: COLORS[index]
        })
      })
      return colorArr
    },
    initChart() {
      window[this.id].setOption(
        merge(
          {},
          {
            backgroundColor: 'transparent',
            tooltip: {
              formatter: function(val) {
                return '区域总表数:' + val.value[2] + '只'
              }
            },
            visualMap: {
              top: 10,
              left: 10,
              min: this.visualMapMin,
              max: this.visualMapMax,
              text: ['严重', '正常'],
              realtime: false,
              calculable: true,
              borderColor: '#1c213e',
              borderWidth: 2,
              backgroundColor: '#212948',
              dimension: 2,
              inRange: {
                color: COLORS,
                opacity: 0.7
              },
              textStyle: {
                color: '#ffffff'
              },
              zlevel: 10
            },
            series: [
              {
                type: 'custom',
                coordinateSystem: 'bmap',
                renderItem: this.renderItem,
                animation: false,
                itemStyle: {
                  emphasis: {
                    color: 'yellow'
                  }
                },
                encode: {
                  tooltip: 2
                },
                data: this.chartData
              }
            ],
            bmap: {
              center: store.getters.mapCenter,
              zoom: 14,
              roam: true,
              animation: false,
              mapStyle: {
                styleJson: config.mapStyleJson
              }
            }
          },
          this.defaultOptions
        ),
        true
      )
      window[`${this.id}-bMap`] = window[this.id]
        .getModel()
        .getComponent('bmap')
        .getBMap()
      const styleOptions = {
        strokeColor: 'red', // 边线颜色。
        fillColor: 'red', // 填充颜色。当参数为空时，圆形将没有填充效果。
        strokeWeight: 3, // 边线的宽度，以像素为单位。
        strokeOpacity: 0.8, // 边线透明度，取值范围0 - 1。
        fillOpacity: 0.6, // 填充的透明度，取值范围0 - 1。
        strokeStyle: 'solid' // 边线的样式，solid或dashed。
      }
      // eslint-disable-next-line no-undef
      window[`${this.id}-drawingManager`] = new BMapLib.DrawingManager(window[`${this.id}-bMap`], {
        isOpen: false, // 是否开启绘制模式
        enableDrawingTool: this.operArea, // 是否显示工具栏
        drawingToolOptions: {
          // eslint-disable-next-line no-undef
          anchor: BMAP_ANCHOR_TOP_RIGHT, // 位置
          // eslint-disable-next-line no-undef
          offset: new BMap.Size(5, 5), // 偏离值
          // eslint-disable-next-line no-undef
          drawingModes: [BMAP_DRAWING_RECTANGLE],
          // eslint-disable-next-line no-undef
          drawingTypes: [BMAP_DRAWING_RECTANGLE],
          scale: 0.6
        },
        circleOptions: styleOptions, // 圆的样式
        polylineOptions: styleOptions, // 线的样式
        polygonOptions: styleOptions, // 多边形的样式
        rectangleOptions: styleOptions // 矩形的样式
      })
      window[`${this.id}-drawingManager`].addEventListener('overlaycomplete', this.overlaycomplete)
    },
    /**
     * @name: areaClickHandle
     * @test: test font
     * @msg: 点击覆盖物
     * @param {type}
     * @return:
     */
    areaClickHandle(params) {
      this.$emit('areaClick', params)
    },
    /**
     * 鼠标框选区域获取经纬度
     * @param  {[type]} e [description]
     * @return {[type]}   [description]
     */
    overlaycomplete(e) {
      this.clearOverlay()
      this.overlays.push(e.overlay)
      const xPath = []
      const yPath = []
      const paths = e.overlay.getPath()
      each(paths, path => {
        const { lng, lat } = path
        xPath.push(lat)
        yPath.push(lng)
      })
      const xMinSize = min(xPath)
      const xMaxSize = max(xPath)
      const yMinSize = min(yPath)
      const yMaxSize = max(yPath)
      this.$emit('checkArea', {
        xMinSize,
        xMaxSize,
        yMinSize,
        yMaxSize
      })
    },
    /**
     * 清除地图选取区域
     * @return {[type]} [description]
     */
    clearOverlay() {
      window[`${this.id}-bMap`].removeOverlay(this.overlays[0])
      this.overlays.length = 0
    },
    /**
     * 获取数据
     * @return {[type]} [description]
     */
    getMapData() {
      window[this.id].showLoading({
        text: '地图规划中,请稍后。。。',
        color: '#2d8cf0',
        textColor: '#2d8cf0',
        maskColor: 'rgba(33, 40, 72,.9)',
        zlevel: 10
      })
      this.fetchData()
    },
    cellSizeCoord() {
      return [
        (this.lngExtent[1] - this.lngExtent[0]) / this.cellCount[0],
        (this.latExtent[1] - this.latExtent[0]) / this.cellCount[1]
      ]
    },
    renderItem(params, api) {
      // const context = params.context;
      const lngIndex = api.value(0)
      const latIndex = api.value(1)
      // const [cellFirst, cellTwo] = this.cellSizeCoord();
      // const coordLeftTop = [
      //   +(this.latExtent[0] + lngIndex * cellFirst).toFixed(6),
      //   +(this.lngExtent[0] + latIndex * cellTwo).toFixed(6)
      // ];
      const pointLeftTop = this.getCoord(params, api, lngIndex, latIndex)
      const pointRightBottom = this.getCoord(params, api, lngIndex + 1, latIndex + 1)

      const data = {
        type: 'rect',
        shape: {
          x: pointLeftTop[0],
          y: pointLeftTop[1],
          width: pointRightBottom[0] - pointLeftTop[0],
          height: pointRightBottom[1] - pointLeftTop[1]
        },
        style: api.style({
          stroke: 'rgba(0,0,0,0.1)'
        }),
        styleEmphasis: api.styleEmphasis()
      }

      return data
    },
    getCoord(params, api, lngIndex, latIndex) {
      window[`${this.id}-bMap`] = window[this.id]
        .getModel()
        .getComponent('bmap')
        .getBMap()
      if (!window[`${this.id}-bMap`]) return
      const point = window[`${this.id}-bMap`].getMapType().getProjection()
      const rightBottomPoint = point.lngLatToPoint({ lng: this.latExtent[1], lat: this.lngExtent[0] })
      const leftTopPoint = point.lngLatToPoint({ lng: this.latExtent[0], lat: this.lngExtent[1] })
      const xMin = leftTopPoint.x
      const xMax = rightBottomPoint.x
      const yMin = rightBottomPoint.y
      const yMax = leftTopPoint.y
      const boxWidth = api.getWidth()
      const boxHeight = api.getHeight()
      const center = point.lngLatToPoint(window[`${this.id}-bMap`].getCenter())
      const zoom = window.Math.pow(2, 18 - window[`${this.id}-bMap`].getZoom())
      const x1 = Math.round((xMax - center.x) / zoom + boxWidth / 2)
      const y1 = Math.round((yMin - center.y) / zoom + boxHeight / 2)
      const x2 = Math.round((xMin - center.x) / zoom + boxWidth / 2)
      const y2 = Math.round((yMax - center.y) / zoom + boxHeight / 2)

      const xMid = (x1 - x2) / this.cellCount[0]
      const yMid = (y2 - y1) / this.cellCount[1]

      const result = [+(x2 + lngIndex * xMid).toFixed(6), +(boxHeight - y2 + latIndex * yMid).toFixed(6)]
      return result
      // const coords = params.context.coords || (params.context.coords = []);
      // const key = lngIndex + '-' + latIndex;
      // const [cellFirst, cellTwo] = this.cellSizeCoord();
      // const ret = coords[key] || (coords[key] = api.coord([
      //   +(this.latExtent[0] + lngIndex * cellFirst).toFixed(6),
      //   +(this.lngExtent[0] + latIndex * cellTwo).toFixed(6)
      // ]));
      // return ret;
    }
  }
}
</script>
<style lang="less">
.heat-map-wrap {
  .chart {
    width: 100%;
    height: 100%;
  }
}
</style>
